﻿using CKS.Core.Framework;
using CKS.PLC.Core.Cache;
using FreeSql;
using FreeSql.Internal.Model;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.Model.Models.ProductionControl;

namespace CKS.PLC.Action.System
{
    /// <summary>
    /// 
    /// 作用类型是加工结果，保存数据到1张表里
    /// </summary>
    public class SaveProcessingResults : PLCAction
    {
        public SaveProcessingResults(DecodeValue _value) : base(_value)
        {
        }


        public virtual AfterSaveResult AfterSaved(SaveArg e)
        {
            return new AfterSaveResult();
        }

        public override void Execute()
        {
            /*
                通用追溯
                根据点位关联的 PlcId\ActionId 查询到动作关联的表
             */
            
               
            var P = Value.Position;
            var act = conn.Select<CksPlcActions>().Where(a => a.ActionType == 1 && a.PlcId == P.PlcId && a.ActionId == P.ActionId)
                .First();
            var table = conn.Select<CksVirtualTable>().Where(a => a.Id == act.BusinessId).First();
            var columns = conn.Select<CksVirtualColumn>().Where(a => a.TableId == act.BusinessId).OrderBy(a => a.Sequence).ToList();
            var replyPos = Value.GetPosition(act.WriteDB, act.ActionId);
            var result = Value.Value.ToInt();
            if (result == 1)
            {
                string triggerNo = $"{Guid.NewGuid().ToString("N")}"; // 触发编号
                //获取分组情况

                var maxLocation = Value.GetMaxLocation();
                var sro = new AfterSaveResult();
                var fsqlTable = ServiceCommon.GetFreesqlTableInfo(table, columns);
                var arg = new SaveArg()
                {
                    TableInfo = fsqlTable,
                    VTable = table,
                    Columns = columns,
                    CksAction = act
                };
                if (maxLocation == 0)
                {
                    CksCollected cl = SaveDataRecord(arg, 0);
                    if(arg.InsertIdentityId>0)
                        sro = AfterSaved(arg);//
                }
                else
                {
                    for (int i = 1; i <= maxLocation; i++)
                    {
                        CksCollected cl = SaveDataRecord(arg, i);
                        if (arg.InsertIdentityId > 0)
                            sro = AfterSaved(arg);//
                    }
                }




                //回复保存完成信号
                WriteInt16(replyPos, 1);
                //EventBus.AddLog($"模块：数据采集；工站：{SiemensClient.PlcInfo.WorkstationCode};保存-{cl.SequenceId}-{cl.PrimaryCode}");
            }
            else if (result == 0)
            {
                //复位上位机的信号
                WriteInt16(replyPos, 0);
                EventBus.AddLog($"{SiemensClient.PlcInfo.PlcAddress} 模块：数据采集；信号：{replyPos.Address};重置");
            }
            

        }

        private CksCollected SaveDataRecord(SaveArg e, int location)
        {
            e.LocationId = location;
            string batchNo = $"{Guid.NewGuid().ToString("N")}"; // 数据批次
            e.VTable.MaxSeqId = GetNextSeq(e.VTable); //获取当前表格的最大虚拟Id
            List<CksCollectedDetails> details = new List<CksCollectedDetails>();
            CksCollected cl = new CksCollected()
            {
                BatchCode = batchNo,
                BatchSuffix = GetSuffix(batchNo, 5),
                CreatedTime = DateTime.Now,
                PlcId = e.CksAction.PlcId,
                SequenceId = e.VTable.MaxSeqId,
                TableId = e.VTable.Id,
                LocationId = location,
            };


            //遍历采集项
            bool saveSecondary = false;
            var dict = new Dictionary<string, object>();
            string mainCode = string.Empty;
            string primaryCode = "";
            foreach (var item in e.Columns)
            {
                string content = "";
                if (item.DataId > 0)
                {
                    var decodeObject = Value.GetLinkDecodeData(location, item.DataId);
                    content = decodeObject.IsCharArray ? decodeObject.CharString : decodeObject.Value.ToString();
                }
                dict[item.ColumnName] = content;
                var model = new CksCollectedDetails()
                {
                    Content = content,
                    ColumnName = item.ColumnName,
                    ColumnId = item.Id,
                    PlcId = e.CksAction.PlcId,
                    TableId = e.VTable.Id,
                    BatchSuffix = GetSuffix(batchNo, 5),
                    BatchCode = batchNo,
                    CreatedTime = cl.CreatedTime
                };
                if (item.DataId > 0)
                {
                    if (item.IsPrimary)
                    {
                        primaryCode = content;
                        cl.PrimaryCode = content;
                        mainCode = content;
                        cl.Suffix_4 = GetSuffix(content);
                    }
                    if (item.IsResult)
                        cl.Result = content.ToInt();
                    if (item.IsSecondary && saveSecondary == false)
                    {
                        cl.SecondaryCode1 = content;
                        saveSecondary = true; //目前只保存1个副码(假如配置多个)
                    }
                }
                else if (item.DataId == 0)
                {
                    if (item.ColumnName == "WorkLocation") //表示需要补全位置
                    {
                        dict[item.ColumnName] = $"{location}";
                    }
                }

                details.Add(model);
            }

            dict["CreatedTime"] = DateTime.Now;
            dict["Nullity"] = false;
            dict["IsDeleted"] = false;

            if(!primaryCode.IsEmpty())
            {
                //如果
                object obj = e.TableInfo.CreateInstance(dict);
                e.InsertIdentityId = conn.Insert<object>().AsType(e.TableInfo.Type).AppendData(obj).ExecuteIdentity(); //保存到动态表
                dict["Id"] = e.InsertIdentityId;
                e.RowData = dict;


                //  conn.Insert(details).ExecuteAffrows();
                // conn.Insert(cl).ExecuteAffrows();
                conn.Update<CksVirtualTable>().SetSource(e.VTable)
                    .UpdateColumns(a => a.MaxSeqId).ExecuteAffrows();
            }
            





            return cl;
        }

        /// <summary>
        /// 内置序列
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private long GetNextSeq(CksVirtualTable table)
        {
            var n = conn.Select<CksVirtualTable>().Where(a => a.TableName == table.TableName).First();
            return n.MaxSeqId + 1;
        }

        /// <summary>
        /// cks2414 生成加工记录流水号
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public long GetNextSerialNumber(string cacheKey )
        {
            lock(ServiceCommon.GetLockObj("GetNextSerialNumber"))
            {
                var n = conn.Select<CksKeyCache>().Where(a => a.CacheKey == cacheKey).First();
                if(n == null)
                {
                    n = new CksKeyCache() { 
                     CacheKey = cacheKey,
                     CreatedTime = DateTime.Now,
                    };
                    conn.Insert(n).ExecuteAffrows();
                }
                return n.MaxSerialNumber + 1;
            }
            
        }

    }

    public class SaveArg
    {
        public TableInfo TableInfo { get; set; }

        public Dictionary<string, object> RowData { get; set; }
        public CksVirtualTable VTable { get; set; }
        public List<CksVirtualColumn> Columns { get; set; }
        public CksPlcActions CksAction { get; set; }
        public long InsertIdentityId { get; set; }

        public int LocationId {  get; set; }
    }


    public class AfterSaveResult
    {
        /// <summary>
        /// 是否继续执行
        /// </summary>
        public bool CanExecute { get; set; } = true;
    }
}
